<template>
    <a-drawer
        v-model:visible="props.visible"
        unmount-on-close
        destroy-on-close
        :width="600"
        title="AI 聊天"
        @cancel="onClose"
        footer-hidden
    >
        <div class="chat-container" ref="containerRef">
            <div
                v-for="(msg, idx) in messages"
                :key="idx"
                :class="['chat-message', msg.role]"
            >
                <div class="avatar">
                    {{ msg.role === "user" ? "你" : "AI" }}
                </div>
                <div class="content"><MdViewer :value="msg.content" /></div>
            </div>
        </div>

        <div class="chat-input">
            <a-textarea
                v-model="prompt"
                :disabled="sending"
                placeholder="输入你的问题，按回车或点击发送"
                @keypress.enter.prevent="send"
                autosize
            />
            <a-button type="primary" :loading="sending" @click="send()"
                >发送</a-button
            >
        </div>
    </a-drawer>
</template>

<script lang="ts" setup>
import { ref, reactive, watch, nextTick } from "vue";
import MdViewer from "./MdViewer.vue";

interface Message {
    role: "user" | "ai";
    content: string;
}

const props = defineProps<{
    visible: boolean;
    onClose: () => void;
}>();

const prompt = ref("");
const sending = ref(false);
const messages = reactive<Message[]>([]);
const containerRef = ref<HTMLElement | null>(null);

watch(
    () => props.visible,
    (val) => {
        if (val) {
            messages.splice(0, messages.length);
        }
    }
);

watch(
    () => messages.length,
    async () => {
        await nextTick();
        if (containerRef.value) {
            containerRef.value.scrollTop = containerRef.value.scrollHeight;
        }
    }
);

function send() {
    if (!prompt.value.trim() || sending.value) return;
    const userText = prompt.value.trim();
    messages.push({ role: "user", content: userText });
    messages.push({ role: "ai", content: "" });
    prompt.value = "";
    sending.value = true;

    const params = new URLSearchParams();
    params.append("prompt", userText);
    params.append("cycleCount", "10");

    const es = new EventSource(
        `http://localhost:8121/api/chat/stream?${params.toString()}`
    );
    es.onmessage = (e) => {
        if (e.data === "[DONE]") {
            es.close();
            sending.value = false;
            return;
        }
        try {
            const chunk = JSON.parse(e.data) as { content: string };
            const last = messages[messages.length - 1];
            last.content += chunk.content;
        } catch (err) {
            console.error("SSE parse error:", err, e.data);
        }
    };
    es.onerror = (err) => {
        console.error("SSE error:", err);
        es.close();
        sending.value = false;
    };
}
</script>

<style scoped>
.chat-container {
    max-height: 60vh;
    overflow-y: auto;
    padding: 16px;
}
.chat-message {
    display: flex;
    margin-bottom: 12px;
}
.chat-message.user {
    flex-direction: row-reverse;
}
.chat-message .avatar {
    width: 48px;
    text-align: center;
    font-weight: bold;
    line-height: 1.5;
}
.chat-message .content {
    max-width: 80%;
    padding: 8px 12px;
    border-radius: 12px;
    background-color: #f5f5f5;
    word-wrap: break-word;
}
.chat-message.user .content {
    background-color: #bae7ff;
}
.chat-input {
    display: flex;
    align-items: center;
    padding: 12px 16px;
    border-top: 1px solid #f0f0f0;
}
.chat-input .arco-input {
    flex: 1;
    margin-right: 8px;
}
</style>